package cn.iocoder.yudao.module.member.service.company;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
import cn.iocoder.yudao.module.member.controller.admin.company.vo.*;
import cn.iocoder.yudao.module.member.convert.company.CompanyConvert;
import cn.iocoder.yudao.module.member.dal.dataobject.company.CompanyDO;
import cn.iocoder.yudao.module.member.dal.dataobject.company.CompanyUserDO;
import cn.iocoder.yudao.module.member.dal.mysql.company.CompanyMapper;
import cn.iocoder.yudao.module.system.api.auth.AdminAuthApi;
import cn.iocoder.yudao.module.system.api.auth.UserSessionApi;
import cn.iocoder.yudao.module.system.api.auth.dto.UserSessionDTO;
import cn.iocoder.yudao.module.system.api.message.MessageApi;
import cn.iocoder.yudao.module.system.api.message.dto.MessageCreateReqDTO;
import cn.iocoder.yudao.module.system.api.permission.RoleApi;
import cn.iocoder.yudao.module.system.api.permission.dto.RoleDTO;
import cn.iocoder.yudao.module.system.api.sms.SmsSendApi;
import cn.iocoder.yudao.module.system.api.sms.dto.send.SmsSendSingleToUserReqDTO;
import cn.iocoder.yudao.module.system.api.tenant.TenantUserApi;
import cn.iocoder.yudao.module.system.api.tenant.dto.TenantCreateVo;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import cn.iocoder.yudao.module.system.api.user.dto.UserUpateReqDTO;
import cn.iocoder.yudao.module.system.api.userRole.AdminUserRoleApi;
import cn.iocoder.yudao.module.system.api.userRole.dto.UserRoleDTO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO;
import cn.iocoder.yudao.module.system.dal.redis.common.CountRedisDAO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.time.Duration;
import java.util.*;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*;

/**
 * 企业管理 Service 实现类
 *
 * @author 周枫皓
 */
@Service
@Validated
@Slf4j
public class CompanyServiceImpl implements CompanyService {

    @Resource
    private CompanyMapper companyMapper;
    @Resource
    private TenantUserApi tenantUserApi;
    @Resource
    private CountRedisDAO countRedisDAO;
    @Resource
    private AdminUserApi adminUserApi;
    @Resource
    private RoleApi roleApi;
    @Resource
    private AdminUserRoleApi adminUserRoleApi;
    @Resource
    private UserSessionApi userSessionApi;
    @Resource
    private AdminAuthApi adminAuthApi;
    @Resource
    private SmsSendApi smsSendApi;
    @Resource
    private MessageApi messageApi;
    /**
     * 角色缓存
     * key：角色编号 {@link RoleDO#getId()}
     *
     * 这里声明 volatile 修饰的原因是，每次刷新时，直接修改指向
     */
    @Getter
    private volatile Map<Long, TenantDO> tenantCache;

    static final String clickBusiness="company_click_count";
    @Override
    @Transactional(rollbackFor = Exception.class) //注意必须要使用事务
    public Long createCompany(CompanyCreateReqVO createReqVO) {
        if(companyMapper.selectCount("credit_code",createReqVO.getCreditCode())>0||companyMapper.selectCount("phone_number",createReqVO.getPhoneNumber())>0){
            throw exception(COMPANY_IS_EXISTS);
        }
        createReqVO.setAuthorizedStatus("authorized");
        //企业视为一个租户,所以必须先创建一个租户 补全租户所需的信息:照抄企业的信息
        TenantCreateVo tenantCreateVo = new TenantCreateVo();
        tenantCreateVo.setUsername(createReqVO.getPhoneNumber());
        tenantCreateVo.setPassword(createReqVO.getPhoneNumber());
        tenantCreateVo.setAccountCount(10);
        tenantCreateVo.setContactName(createReqVO.getApplyUserName());
        tenantCreateVo.setContactMobile(createReqVO.getPhoneNumber());
        tenantCreateVo.setName(createReqVO.getCreditCode());
        tenantCreateVo.setStatus(0);
        tenantCreateVo.setExpireTime(DateUtils.buildTime(2099,12,30,0,0,0));
        tenantCreateVo.setPackageId(113L);
        tenantCreateVo.setDeptName(createReqVO.getDept());
        //TODO
        //... setXXX
        Long tenantId = tenantUserApi.createTenant(tenantCreateVo);
        //创建一个企业待插入对象
        CompanyDO company = CompanyConvert.INSTANCE.convert(createReqVO);
        company.setChecker(SecurityFrameworkUtils.getLoginUser().getUsername());
        company.setStatus("-1");
        company.setUpdater(WebFrameworkUtils.getLoginUserName());
        company.setCreator(WebFrameworkUtils.getLoginUserName());
        //强制使用指定租户，执行对应的逻辑: 设置上下文租户ID,因为entity不支持显式setTenantId();
        TenantUtils.execute(tenantId, () -> {
            //执行创建企业insert
            companyMapper.insert(company);
        });
        //企业id
        AdminUserRespDTO userRespDTO= adminUserApi.getUserNoTenant(createReqVO.getPhoneNumber());
        UserUpateReqDTO userUpateReqDTO=new UserUpateReqDTO();
        userUpateReqDTO.setId(userRespDTO.getId());
        userUpateReqDTO.setCompanyId(company.getId());
        userUpateReqDTO.setEmail(createReqVO.getEmail());
        userUpateReqDTO.setUnrealFlag(createReqVO.getUnrealFlag());
        TenantUtils.execute(tenantId, () -> {
            //执行创建企业insert
            adminUserApi.updateUser(userUpateReqDTO);
        });

        // 返回
        return company.getId();
    }

    @Override
    public void updateCompany(CompanyUpdateReqVO updateReqVO) {
        // 校验存在
        this.validateCompanyExists(updateReqVO.getId());
        // 更新
        CompanyDO updateObj = CompanyConvert.INSTANCE.convert(updateReqVO);
        updateObj.setUpdater(WebFrameworkUtils.getLoginUserName());
        updateObj.setUpdateTime(new Date());
        companyMapper.updateById(updateObj);
    }

    @Override
    public void updateOrderNum(@Valid CompanyUpdateReqVO updateReqVO) {
        CompanyDO companyDO = companyMapper.selectById(updateReqVO.getId());
        if(null==companyDO){
            throw exception(COMPANY_NOT_EXISTS);
        }
        CompanyDO updateObj =new CompanyDO();
        updateObj.setUpdater(WebFrameworkUtils.getLoginUserName());
        updateObj.setUpdateTime(new Date());
        updateObj.setId(updateReqVO.getId());
        if(null==companyDO.getOrderNum()|| 0==companyDO.getOrderNum()){
            LambdaQueryWrapper<CompanyDO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.select(CompanyDO::getOrderNum) // 填入需要查询的字段
                    .orderByDesc(CompanyDO::getOrderNum) // 按该字段降序排序
                    .last("LIMIT 1"); // 只返回最大值的一条记录
            CompanyDO result = companyMapper.selectOne(queryWrapper);
            if(null==result){
                updateObj.setOrderNum(1);
            }else{
                updateObj.setOrderNum(result.getOrderNum()+1);
            }
        }else{
            updateObj.setOrderNum(0);
        }
        companyMapper.updateById(updateObj);
    }

    @Override
    public void deleteCompany(Long id) {
        // 校验存在
        this.validateCompanyExists(id);
        // 删除
        companyMapper.deleteById(id);
    }

    @Override
    public CompanyDO getCompanyById(Long id) {
        return companyMapper.selectById(id);
    }

    private void validateCompanyExists(Long id) {
        if (companyMapper.selectById(id) == null) {
            throw exception(COMPANY_NOT_EXISTS);
        }
    }

    @Override
    public CompanyDO getCompany(Long id,int type) {
        CompanyDO companyDO=companyMapper.selectById(id);
        if(type==1){
            if(companyDO!=null){
                Integer count=addCount(id);
                companyDO.setClickCount(count);
                updateCompanyCount(companyDO);
            }
        }
        return companyDO;
    }

    @Override
    @TenantIgnore
    public CompanyDO getCompanyNotenant(Long id) {
        return companyMapper.selectById(id);
    }

    @Override
    public CompanyDO getCompanyByPhone(String phone) {
        return companyMapper.selectOne("phone_number",phone);
    }

    @Async
    public void updateCompanyCount(CompanyDO updateReqVO) {
        // 更新
        companyMapper.updateById(updateReqVO);
    }

    @Override
    public CompanyDO getCompanyByTenantId(Long tenantId) {
        return companyMapper.selectOne("deleted", 0l);
    }

    @Override
    public List<CompanyDO> getCompanyList(Collection<Long> ids) {
        return companyMapper.selectBatchIds(ids);
    }

    @Override
    public List<CompanyDO> getCompanyAllByIds(List<Long> ids) {
        return companyMapper.getCompanyAllByIds(ids);
    }

    @Override
    public List<CompanyDO> getCompanyByMobiles(List<String> mobiles) {
        return companyMapper.selectList(new QueryWrapper<CompanyDO>().in("phone_number",mobiles));
    }

    @Override
    public List<CompanyDO> getCompanyList() {
        return companyMapper.selectList("authorized_status", "authorized");
    }


    @Override
    public PageResult<CompanyDO> getCompanyPage(CompanyPageReqVO pageReqVO) {
        return companyMapper.selectPage(pageReqVO);
    }

    @Override
    public List<CompanyDO> getCompanyList(CompanyExportReqVO exportReqVO) {
        return companyMapper.selectList(exportReqVO);
    }

    public Integer addCount(Long id) {
        Integer newCount=0;
        Duration d = Duration.ofDays(1);
        String count=countRedisDAO.get(clickBusiness,id.toString());
        if(StringUtils.isEmpty(count)){
            CompanyDO companyDO=companyMapper.selectById(id);
            if(companyDO.getClickCount()==null){
                newCount=0;
                countRedisDAO.set(clickBusiness,id.toString(),newCount,d);
            }else{
                Integer clickCount=companyDO.getClickCount();
                newCount=clickCount+1;
                countRedisDAO.set(clickBusiness,id.toString(),newCount,d);
            }
        }else{
            Integer clickCount=Integer.parseInt(count);
            newCount=clickCount+1;
            countRedisDAO.set(clickBusiness,id.toString(),newCount,d);
        }
        return newCount;

    }


    @Override
    public Boolean authenticationCompany(@Valid Long id,String authorizedStatus,String remark) {
            CompanyDO company = companyMapper.selectById(id);
            AdminUserRespDTO adminUserRespDTO=adminUserApi.getUser(company.getPhoneNumber());
            String title;
            String message;
            if (company.getAuthorizedStatus().equals("authorized")) {
                exception(COMPANY_IS_AUTHORIZED);
            }else{
                if(authorizedStatus.equals("reject")){
                    company.setAuthorizedStatus(authorizedStatus);
                    company.setRemark(remark);
                    company.setChecker(SecurityFrameworkUtils.getLoginUser().getUsername());
                    int i = companyMapper.updateById(company);
                    title="身份认证审核失败";
                    message="认证信息系统审核失败，失败原因为"+remark+"，请重新进行身份实名认证。";
                    List<Long> ids= adminUserApi.getUserIdsByTenant(2l);
                    for (Long id1:ids) {
                        sendmessage(1l,id1,title,message);
                    }
                    return i>0;
                }else {
                    //企业视为一个租户,所以必须先创建一个租户 补全租户所需的信息:照抄企业的信息
                    TenantCreateVo tenantCreateVo = new TenantCreateVo();
                    tenantCreateVo.setUsername(company.getPhoneNumber());
                    tenantCreateVo.setPassword(adminUserRespDTO.getPassword());
                    tenantCreateVo.setAccountCount(10);
                    tenantCreateVo.setContactMobile(company.getPhoneNumber());
                    tenantCreateVo.setContactName(company.getApplyUserName());
                    tenantCreateVo.setName(company.getCreditCode());
                    tenantCreateVo.setExpireTime(DateUtils.buildTime(2099, 12, 31));
                    tenantCreateVo.setStatus(0);
                    tenantCreateVo.setPackageId(113L);
                    tenantCreateVo.setDeptName(company.getDept());
                    Long tenantId = tenantUserApi.createTenant(tenantCreateVo,adminUserRespDTO);
                    company.setAuthorizedStatus(authorizedStatus);
                    company.setRemark(remark);
                    company.setChecker(SecurityFrameworkUtils.getLoginUser().getUsername());
                    company.setTenantId(tenantId);
                    companyMapper.updateById(company);
                    UserSessionDTO userSessionDTO=userSessionApi.getLoginUserSession(adminUserRespDTO.getId());
                    if(userSessionDTO!=null){
                        // 刷新 LoginUser 缓存
                        userSessionApi.deleteUserSession(userSessionDTO.getId());
                        LoginUser loginUser=new LoginUser();
                        BeanUtils.copyProperties(adminUserRespDTO,loginUser);
                        loginUser.setCompanyId(company.getId());
                        adminAuthApi.refreshLoginUserCache(userSessionDTO.getId(),loginUser);
                    }
                    title="身份认证审核成功";
                    message="恭喜，您已身份认证，认证信息系统审核成功，可以编辑职位啦~";
                    List<Long> ids= adminUserApi.getUserIdsByTenant(2l);
                    for (Long id1:ids) {
                        sendmessage(1l,id1,title,message);
                    }
                    this.sendSms(company,authorizedStatus);
                return  true;
                }


            }
            return false;
    }

    @Async
    void sendmessage(Long type, Long id, String title, String messageText){
        MessageCreateReqDTO messageCreateReqVO=new MessageCreateReqDTO();
        messageCreateReqVO.setPhone("");
        messageCreateReqVO.setType(type);
        messageCreateReqVO.setStatus("5");
        messageCreateReqVO.setUserId(id);
        messageCreateReqVO.setStudentName("系统管理员");
        messageCreateReqVO.setRemark(messageText);
        messageCreateReqVO.setTitle(title);
        messageApi.sendMessage(messageCreateReqVO);
    }
    /**
     * 发送面试通知短信
     * @param company authorizedStatus
     */
    private void sendSms(CompanyDO company,String authorizedStatus){
        SmsSendSingleToUserReqDTO smsSendSingleToUserReqDTO=new SmsSendSingleToUserReqDTO();
        smsSendSingleToUserReqDTO.setUserId(SecurityFrameworkUtils.getLoginUserId());
        smsSendSingleToUserReqDTO.setMobile(company.getPhoneNumber());
        smsSendSingleToUserReqDTO.setTemplateCode("aliyun-company-examine-message");
        Map<String,Object> paraMap=new HashMap<>();
        paraMap.put("companyName",company.getCompanyName());
        paraMap.put("result",convertAuthorizedStatus(authorizedStatus));
        smsSendSingleToUserReqDTO.setTemplateParams(paraMap);
        smsSendApi.sendSingleSmsToAdmin(smsSendSingleToUserReqDTO);
    }
    private String convertAuthorizedStatus(String authorizedStatus){
            if(authorizedStatus.equals("authorized")){
                return "通过";
            }
            if(authorizedStatus.equals("reject")){
                return "未通过";
            }
            return "";
    }


    @Override
    public PageResult<CompanyUserDO> getCompanyUserPage(CompanyUserPageReqVO pageReqVO) {
        Integer total = companyMapper.countCompanyUser(pageReqVO);
        if (total <= 0) {
            return PageResult.empty();
        }
        List<CompanyUserDO> companyUserPage = companyMapper.getCompanyUserPage(pageReqVO);
        return PageResult.build(companyUserPage, total);
    }
    @Override
    public List<CompanyUserDO> getCompanyUserList(CompanyUserPageReqVO pageReqVO) {
        pageReqVO.setPageSize(100000);
        List<CompanyUserDO> companyUserPage = companyMapper.getCompanyUserPage(pageReqVO);
        return companyUserPage;
    }

    @Override
    public CompanyUserDO getCompanyUser(CompanyUserReqVO reqVO) {
        // 校验存在
        CompanyDO companyDO=this.getCompany(reqVO.getCompanyId(),0);
        if(companyDO==null){
            throw exception(COMPANY_NOT_EXISTS);
        }
        AdminUserRespDTO adminUserRespDTO=adminUserApi.getUser(reqVO.getUserId());
        List<UserRoleDTO> userRoleDTO=adminUserRoleApi.getUserRoleByUserId(reqVO.getUserId());
        RoleDTO roleDTO=roleApi.getRole(userRoleDTO.get(0).getRoleId());
        if(userRoleDTO==null){
            throw exception(USER_NOT_EXISTS);
        }
        CompanyUserDO companyUserDO=new CompanyUserDO();
        companyUserDO.setCompanyId(companyDO.getId());
        companyUserDO.setCardNo(companyDO.getCardNo());
        companyUserDO.setUserId(adminUserRespDTO.getId());
        companyUserDO.setDept(companyDO.getDept());
        companyUserDO.setJob(companyDO.getJob());
        companyUserDO.setUnrealFlag(adminUserRespDTO.getUnrealFlag());
        companyUserDO.setCompanyName(companyDO.getCompanyName());
        companyUserDO.setAuthorizedStatus(companyDO.getAuthorizedStatus());
        companyUserDO.setCreateTime(adminUserRespDTO.getCreateTime());
        companyUserDO.setMobile(adminUserRespDTO.getMobile());
        companyUserDO.setNickname(adminUserRespDTO.getNickname());
        companyUserDO.setPhoneNumber(companyDO.getPhoneNumber());
        companyUserDO.setRoleType(roleDTO.getName());
        companyUserDO.setLoginDate(adminUserRespDTO.getLoginDate());
        companyUserDO.setEmail(companyDO.getEmail());
        companyUserDO.setProvince(companyDO.getProvince());
        companyUserDO.setCity(companyDO.getCity());
        companyUserDO.setTel(companyDO.getTel());
        companyUserDO.setCreditCode(companyDO.getCreditCode());
        companyUserDO.setBusinessLicense(companyDO.getBusinessLicense());
        companyUserDO.setIndustryType(companyDO.getIndustryType());
        companyUserDO.setPostCode(companyDO.getPostCode());
        companyUserDO.setBusinessStatus(companyDO.getBusinessStatus());
        companyUserDO.setRegisteredCapital(companyDO.getRegisteredCapital());
        companyUserDO.setEstablishDate(companyDO.getEstablishDate());
        companyUserDO.setLegalPerson(companyDO.getLegalPerson());
        companyUserDO.setScale(companyDO.getScale());
        companyUserDO.setStatus(companyDO.getStatus());
        companyUserDO.setCompanyType(companyDO.getCompanyType());
        companyUserDO.setCompanyPicture(companyDO.getCompanyPicture());
        companyUserDO.setBusinessScope(companyDO.getBusinessScope());
        companyUserDO.setCompanyLogo(companyDO.getCompanyLogo());
        companyUserDO.setIndustry(companyDO.getIndustry());
        companyUserDO.setIntroduction(companyDO.getIntroduction());
        companyUserDO.setEnvironment(companyDO.getEnvironment());
        companyUserDO.setCompanyAddress(companyDO.getCompanyAddress());
        companyUserDO.setCompanyCoordinate(companyDO.getCompanyCoordinate());
        companyUserDO.setSubCompanyRelationshipCertificatePicture(companyDO.getSubCompanyRelationshipCertificatePicture());
        companyUserDO.setSubCompanyRelationshipCertificateWord(companyDO.getSubCompanyRelationshipCertificateWord());
        companyUserDO.setTopStatus(companyDO.getTopStatus());
        companyUserDO.setApplyUserName(companyDO.getApplyUserName());
        companyUserDO.setLoginDate(adminUserRespDTO.getLoginDate());
        companyUserDO.setRegisteredAddress(companyDO.getRegisteredAddress());
        companyUserDO.setAuthenticationBackPictureUrl(companyDO.getAuthenticationBackPictureUrl());
        companyUserDO.setAuthenticationFrontPictureUrl(companyDO.getAuthenticationFrontPictureUrl());
        return companyUserDO;
    }

    @Override
    public void deleteCompanyUser(CompanyUserReqVO reqVO) {
        if(reqVO.getCompanyId()>0) {
            CompanyDO companyDO = this.getCompany(reqVO.getCompanyId(), 0);
            if (companyDO == null) {
                throw exception(COMPANY_NOT_EXISTS);
            }
            companyMapper.deleteById(companyDO);
        }
        if(reqVO.getUserId()>0) {
            AdminUserRespDTO adminUserRespDTO= adminUserApi.getUser(reqVO.getUserId());
            if (adminUserRespDTO == null) {
                throw exception(COMPANY_NOT_EXISTS);
            }
            adminUserApi.deleteUser(reqVO.getUserId());

            tenantUserApi.deleteTenant(reqVO.getUserId());

//            roleApi.deleteRoleByTenantId(adminUserRespDTO.getTenantId());
        }


    }

    @Override
    public List<CompanyDO> getHotCompanyPage(CompanyPageReqVO pageReqVO) {
        if(pageReqVO.getPageSize()==null || pageReqVO.getPageSize()==10){
            pageReqVO.setPageSize(50);
        }
        List<CompanyDO> companyUserPage = companyMapper.getHotCompanyPage(pageReqVO);
        return companyUserPage;
    }

    @Override
    public List<CompanyDO> getCompanyByIsHot() {
        return companyMapper.getCompanyByIsHot();
    }

    @Override
    public Integer getCompanyRegistCount(String startDate,String endDate){
       return companyMapper.getCompanyRegistCount( startDate, endDate);
    }
}
